using Glpt.Common;
using Glpt.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Text;

namespace Glpt.Task
{
    /// <summary>
    /// 复制文件任务
    /// </summary>
    public class CopyFileTask
    {
        private BackgroundWorker bwt = null;
        private const string ATTR_PARAM_VALUE = "@PARAM_VALUE";
        private Dictionary<string, string> exec_params = new Dictionary<string, string>();
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        public CopyFileTask()
        {
        }
        /// <summary>
        /// 测试接口
        /// </summary>
        /// <param name="function_id">功能号</param>
        /// <param name="tradedate">业务日期</param>
        public void SetParams(string function_id, string tradedate)
        {
            SetParams(function_id, tradedate, "");
        }
        /// <summary>
        /// 测试接口
        /// </summary>
        /// <param name="function_id">功能号</param>
        /// <param name="tradedate">业务日期</param>
        public void SetParams(string function_id, string tradedate, string exec_value)
        {
            SetParams(0, function_id, "", tradedate, exec_value);
        }
        /// <summary>
        /// 参数设置
        /// </summary>
        /// <param name="db_no">数据库编号</param>
        /// <param name="function_id">功能编号</param>
        /// <param name="task_id">任务编号</param>
        /// <param name="tradedate">业务日期</param>
        public void SetParams(int db_no, string function_id, string task_id, string tradedate)
        {
            SetParams(db_no, function_id, task_id, tradedate, "");
        }
        /// <summary>
        /// 参数设置
        /// </summary>
        /// <param name="db_no">数据库编号</param>
        /// <param name="function_id">功能编号</param>
        /// <param name="task_id">任务编号</param>
        /// <param name="tradedate">业务日期</param>
        /// <param name="exec_value">参数值</param>
        public void SetParams(int db_no, string function_id, string task_id, string tradedate, string exec_value)
        {
            string copy_id_name = "";
            string param_value = "";
            if (exec_value.StartsWith(":"))
                copy_id_name = exec_value.Substring(1);
            else if (exec_value.StartsWith("%"))
                copy_id_name = exec_value;
            else
                param_value = exec_value;
            BaseInterFace bif = new BaseInterFace(db_no);
            string sql = "SELECT * FROM TB_COPY_LIST WHERE TASK_FUNCTION_ID=" + function_id;
            if (copy_id_name.Length > 0)
            {
                if (Funcs.IsInt(copy_id_name))
                    sql += " AND COPY_ID=" + copy_id_name;
                else
                    sql += " AND SOURCE_PATH LIKE '" + copy_id_name + "'";
            }
            sql += " AND ENABLE_FLAG='1' ORDER BY COPY_ID";
            DataTable dt_list = bif.ExecSelect(sql);
            DataRow[] drs = dt_list.Select("COPY_ID=-1");//动态取
            if (drs.Length > 0)
                dt_list = CommFuns.GetDynamicProc(dt_list, drs[0]["SOURCE_PATH"].ToString(), function_id, tradedate);
            string errid = "";
            string errmsg = "";
            foreach (DataRow dr in dt_list.Rows)
            {
                if (bwt != null && bwt.CancellationPending)
                    throw new Exception("线程被取消");
                try
                {
                    string BUSI_DATE = tradedate;
                    string DATE_EXP = Funcs.ReplaceWord(dr["DATE_EXP"].ToString(), BUSI_DATE).Replace(ATTR_PARAM_VALUE, param_value);
                    int ParamsCount = 1;
                    DataTable dt_params = null;
                    if (DATE_EXP.Length > 0)
                    {
                        dt_params = CommFuns.GetDynamicFunc(bif, DATE_EXP, "BUSI_DATE");
                        ParamsCount = dt_params.Rows.Count;
                        if (ParamsCount == 0)
                            continue;
                        else if (ParamsCount == 1)
                            CommFuns.AddParams(exec_params, dt_params);
                        if (exec_params.ContainsKey("@BUSI_DATE") && exec_params["@BUSI_DATE"].Length > 0)
                            BUSI_DATE = exec_params["@BUSI_DATE"];
                        if (exec_params.ContainsKey("@BEGIN_DATE") && exec_params["@BEGIN_DATE"].Length == 8 && !exec_params.ContainsKey("@C_BEGIN_DATE"))
                            CommFuns.AddParams(exec_params, "C_BEGIN_DATE", Funcs.StrToDataTime(exec_params["@BEGIN_DATE"]).ToString("yyyy-MM-dd"));
                        if (exec_params.ContainsKey("@END_DATE") && exec_params["@END_DATE"].Length == 8 && !exec_params.ContainsKey("@C_END_DATE"))
                            CommFuns.AddParams(exec_params, "C_END_DATE", Funcs.StrToDataTime(exec_params["@END_DATE"]).ToString("yyyy-MM-dd"));
                    }
                    string encode_name = dr["ENCODE"].ToString();
                    bool recursive = dr["SEARCH_OPTION"].ToString().Equals("1");
                    SearchOption search_option = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
                    for (int i = 0; i < ParamsCount; i++)
                    {
                        string source = Funcs.ReplaceWord(dr["SOURCE_PATH"].ToString(), BUSI_DATE).Replace(ATTR_PARAM_VALUE, param_value);
                        string destination = Funcs.ReplaceWord(dr["TARGET_PATH"].ToString(), BUSI_DATE).Replace(ATTR_PARAM_VALUE, param_value);
                        if (ParamsCount > 1)
                        {
                            foreach (DataColumn dc in dt_params.Columns)
                            {
                                string param_name = "@" + dc.ColumnName;
                                string data_value = dt_params.Rows[i][dc].ToString();
                                source = source.Replace(param_name, Funcs.ReplaceWord(data_value, BUSI_DATE));
                                destination = destination.Replace(param_name, Funcs.ReplaceWord(data_value, BUSI_DATE));
                            }
                        }
                        foreach (string param_name in exec_params.Keys)
                        {
                            source = source.Replace(param_name, Funcs.ReplaceWord(exec_params[param_name], BUSI_DATE));
                            destination = destination.Replace(param_name, Funcs.ReplaceWord(exec_params[param_name], BUSI_DATE));
                        }
                        if (source.Length == 0 && destination.Length > 0)
                        {
                            DeleteFile(destination, recursive);
                        }
                        else if (source.Length > 0 && destination.Length == 0)
                        {
                            DeleteFile(source, recursive);
                        }
                        else if (FilePath.IsFTP(source))//从ftp下载
                        {
                            string path = FtpServerInfo.GetParentPath(source);
                            string searchPattern = (path.Length == 0 ? "*" : source.Substring(path.Length + 1));
                            if (searchPattern.Length == 0) searchPattern = "*";
                            FtpServerInfo ser = new FtpServerInfo(source);
                            ser.UsePassive = true;
                            if (searchPattern.Contains("*") || searchPattern.Contains("?"))
                            {
                                try
                                {
                                    List<string> lst = ser.GetFileList(search_option);
                                    foreach (string val in lst)
                                    {
                                        string source_new = path + "/" + val;
                                        string destination_new = Path.Combine(destination, val.Replace("/", DataFuns.DirSeparator));
                                        ser.SetURL(source_new);
                                        ser.DownloadFile(destination_new);
                                        if (encode_name.Length > 0)//转码
                                            CopyEncoding(destination_new, destination_new, CommFuns.GetEncoding(encode_name));
                                    }
                                }
                                catch
                                {
                                    if (ser.CheckDirectoryExists())
                                        throw;
                                }
                            }
                            else
                            {
                                if (Directory.Exists(destination) || destination.EndsWith(DataFuns.DirSeparator))
                                {
                                    destination = Path.Combine(destination, new FileInfo(ser.Path.Replace("/", DataFuns.DirSeparator)).Name);
                                }
                                ser.DownloadFile(destination);
                                if (encode_name.Length > 0)//转码
                                    CopyEncoding(destination, destination, CommFuns.GetEncoding(encode_name));
                            }
                        }
                        else if (FilePath.IsFTP(destination))//上传到ftp
                        {
                            int idx = source.LastIndexOf(DataFuns.DirSeparator);
                            if (idx > 0)
                            {
                                DirectoryInfo dinfo = new DirectoryInfo(source.Substring(0, idx));
                                if (dinfo.Exists)
                                {
                                    string searchPattern = source.Substring(idx + 1);
                                    if (searchPattern.Length == 0) searchPattern = "*.*";
                                    FileInfo[] files = dinfo.GetFiles(searchPattern, search_option);
                                    FtpServerInfo ser = new FtpServerInfo();
                                    ser.UsePassive = true;
                                    string path = FtpServerInfo.GetParentPath(destination);
                                    foreach (FileInfo file in files)
                                    {
                                        string url = destination;
                                        string name = file.FullName.Substring(dinfo.FullName.Length + 1).Replace(DataFuns.DirSeparator, "/");
                                        if (searchPattern.Contains("*") || searchPattern.Contains("?") || files.Length > 1 || url.EndsWith("/"))
                                            url = path + "/" + name;
                                        ser.SetURL(url);
                                        ser.UploadFile(file.FullName);
                                    }
                                }
                            }
                        }
                        else if (source.Equals("okfile"))//写结束标志文件
                        {
                            if (errid.Length > 0) continue;
                            FileInfo file = new FileInfo(destination);
                            if (!file.Directory.Exists) file.Directory.Create();
                            File.WriteAllText(destination, "", DataFuns.DefaultEncoding);
                        }
                        else
                            CopyFiles(source, destination, search_option, encode_name, true);
                    }
                }
                catch (Exception ex)
                {
                    if (errid.Length > 0) errid += ",";
                    errid += dr["COPY_ID"].ToString();
                    if (errmsg.Length == 0)
                        errmsg = ex.Message;
                }
            }
            if (errid.Length > 0)
                throw new Exception(errid + ":" + errmsg);
        }
        public static int CopyFiles(string source, string destination, SearchOption search_option, string encode_name, bool overwrite)
        {
            int icount = 0;
            if (File.Exists(source))
            {
                if (Directory.Exists(destination) || destination.EndsWith(DataFuns.DirSeparator))
                {
                    destination = Path.Combine(destination, new FileInfo(source).Name);
                }
                FileInfo destfile = new FileInfo(destination);
                DirectoryInfo dirinfo = destfile.Directory;
                if (!dirinfo.Exists) dirinfo.Create();
                if (overwrite || !destfile.Exists)
                {
                    if (encode_name.Length > 0)//转码
                        CopyEncoding(source, destination, CommFuns.GetEncoding(encode_name));
                    else
                    {
                        if (destfile.Exists && destfile.IsReadOnly)
                            destfile.IsReadOnly = false;
                        File.Copy(source, destination, overwrite);
                    }
                    icount++;
                }
            }
            else if (Directory.Exists(source))
            {
                DirectoryInfo dirinfo = new DirectoryInfo(destination);
                if (!dirinfo.Exists) dirinfo.Create();
                icount = CopyFiles(source, destination, search_option, overwrite);
            }
            else
            {
                int idx = source.LastIndexOf(DataFuns.DirSeparator);
                if (idx > 0)
                {
                    DirectoryInfo dinfo = new DirectoryInfo(source.Substring(0, idx));
                    if (dinfo.Exists)
                    {
                        FileInfo[] files = dinfo.GetFiles(source.Substring(idx + 1), search_option);
                        foreach (FileInfo file in files)
                        {
                            bool copyfile = false;
                            string destFileName = "";
                            if (Directory.Exists(destination) || destination.EndsWith(DataFuns.DirSeparator))
                            {
                                if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);
                                destFileName = Path.Combine(destination, file.Name);
                            }
                            else
                            {
                                destFileName = destination;
                                copyfile = true;
                            }
                            if (overwrite || !File.Exists(destFileName))
                            {
                                if (encode_name.Length > 0)//转码
                                    CopyEncoding(file.FullName, destFileName, CommFuns.GetEncoding(encode_name));
                                else
                                {
                                    FileInfo destFile = new FileInfo(destFileName);
                                    if (!destFile.Directory.Exists)
                                        destFile.Directory.Create();
                                    file.CopyTo(destFileName, overwrite);
                                }
                                icount++;
                            }
                            if (copyfile)
                                break;
                        }
                    }
                }
            }
            return icount;
        }

        /// <summary>
        /// 复制指定目录的文件
        /// </summary>
        /// <param name="sourceDir">原始目录</param>
        /// <param name="targetDir">目标目录</param>
        /// <param name="searchOption">复制子目录</param>
        public static int CopyFiles(string sourceDir, string targetDir, SearchOption searchOption, bool overwrite)
        {
            int icount = 0;
            //复制当前目录文件
            foreach (string sourceFileName in Directory.GetFiles(sourceDir))
            {
                string targetFileName = Path.Combine(targetDir, sourceFileName.Substring(sourceFileName.LastIndexOf(DataFuns.DirSeparator) + 1));
                if (overwrite || !File.Exists(targetFileName))
                {
                    File.Copy(sourceFileName, targetFileName, overwrite);
                    icount++;
                }
            }
            //复制子目录
            if (searchOption.Equals(SearchOption.AllDirectories))
            {
                foreach (string sourceSubDir in Directory.GetDirectories(sourceDir))
                {
                    string targetSubDir = Path.Combine(targetDir, sourceSubDir.Substring(sourceSubDir.LastIndexOf(DataFuns.DirSeparator) + 1));
                    if (!Directory.Exists(targetSubDir))
                        Directory.CreateDirectory(targetSubDir);
                    int icount2 = CopyFiles(sourceSubDir, targetSubDir, searchOption, overwrite);
                    icount += icount2;
                }
            }
            return icount;
        }

        /// <summary>
        /// 复制文件并自动转码
        /// </summary>
        /// <param name="source">源文件</param>
        /// <param name="destination">目标文件</param>
        /// <param name="encode">编码</param>
        private static void CopyEncoding(string source, string destination, Encoding encode)
        {
            string content = File.ReadAllText(source, encode);
            FileInfo file = new FileInfo(destination);
            if (!file.Directory.Exists) file.Directory.Create();
            File.WriteAllText(destination, content, DataFuns.DefaultEncoding);
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="path">目录或文件路径</param>
        /// <param name="recursive">是否删除子目录</param>
        private static void DeleteFile(string path, bool recursive)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            else if (Directory.Exists(path))
            {
                //删除文件
                foreach (string sourceFileName in Directory.GetFiles(path))
                {
                    File.Delete(sourceFileName);
                }
                //删除目录
                if (recursive)
                {
                    foreach (string sourceSubDir in Directory.GetDirectories(path))
                    {
                        Directory.Delete(sourceSubDir, recursive);
                    }
                }
            }
        }

        /// <summary>
        /// 后台任务对象
        /// </summary>
        public BackgroundWorker BackgroundWorkerTask
        {
            get
            {
                return bwt;
            }
            set
            {
                bwt = value;
            }
        }

        /// <summary>
        /// 释放内存
        /// </summary>
        public void Dispose()
        {
            try
            {
                GC.Collect();
            }
            catch { }
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~CopyFileTask()
        {
            Dispose();
        }
    }
}
